package com.xuecheng.auth.web.controller;

import com.xuecheng.api.auth.AuthControllerApi;
import com.xuecheng.auth.service.AuthService;
import com.xuecheng.framework.domain.ucenter.ext.AuthToken;
import com.xuecheng.framework.domain.ucenter.request.LoginRequest;
import com.xuecheng.framework.domain.ucenter.response.AuthCode;
import com.xuecheng.framework.domain.ucenter.response.JwtResult;
import com.xuecheng.framework.domain.ucenter.response.LoginResult;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.ResponseResult;
import com.xuecheng.framework.utils.CookieUtil;
import com.xuecheng.framework.utils.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @author: gongfy
 * @create: 2020/8/25 17:28
 * @Description: 用户认证controller
 */
@RestController
//@RequestMapping("/openapi/auth")  todo 配置文件中 配置了server.servlet.context-path: /auth
@RequestMapping("/")
@Slf4j
public class AuthController implements AuthControllerApi {

    @Autowired
    private AuthService authService;

    @Value("${auth.clientId}")
    String clientId;
    @Value("${auth.clientSecret}")
    String clientSecret;
     @Value("${auth.cookieDomain}")
    String cookieDomain;
    @Value("${auth.cookieMaxAge}")
    int cookieMaxAge;
    @Value("${auth.tokenValiditySeconds}")
    int tokenValiditySeconds;

    /**
     * @Author: gongfy
     * @Param: username 账户 password 密码
     * @Return:  LoginResult 登录结果 成功则返回token令牌
     * @Date: 2020/8/26 15:21
     * @Description: 用户登录认证 1.申请令牌令牌（存入reids） 2.将短令牌存入cookie，并返回前端 todo 返回前端作用是啥
     **/
    @Override
    @PostMapping("/userlogin")
    public LoginResult login(LoginRequest loginRequest) {// todo 为什么加了Requestbody就用 postman访问不通了
        //校验账号是否输入
        if (loginRequest == null || StringUtils.isEmpty(loginRequest.getUsername())){
            ExceptionCast.cast(AuthCode.AUTH_USERNAME_NONE);
        }
        //校验密码是否输入
        if (StringUtils.isEmpty(loginRequest.getPassword())){ ExceptionCast.cast(AuthCode.AUTH_PASSWORD_NONE);}
        //1.申请令牌     httpbasic 客户端Id和客户端密码会匹配数据库oauth_client_details表中的客户端id及客户端密码
        AuthToken authToken = null;
        try {
            authToken = authService.login(loginRequest.getUsername(),loginRequest.getPassword(),clientId,clientSecret);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            //throw new RuntimeException("申请令牌失败！");
            return new LoginResult(CommonCode.FAIL,null);
        }
        //2.将短令牌存入cookie
        String jit_token = authToken.getJti_token();
        this.saveTokenToCookie(jit_token);
        return new LoginResult(CommonCode.SUCCESS,jit_token);
    }
    //将令牌保存到cookie
    public void saveTokenToCookie(String jitToken){
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        //添加cookie 认证令牌，最后一个参数设置为false，表示允许浏览器获取
        CookieUtil.addCookie(response,cookieDomain,"/","uid",jitToken,cookieMaxAge,false);
    }

    //将令牌保存到cookie
    public void delTokenFromCookie(String jitToken){
        //获取reponse对象：根据RequestAttributes强转成子类ServletRequestAttributes调用getResponse()方法获取
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        //添加cookie 认证令牌，最后一个参数设置为false，表示允许浏览器获取
        CookieUtil.addCookie(response,cookieDomain,"/","uid",jitToken,0,false);
    }
    /**
    * @Author: gongfy
    * @Date: 2020/8/26 15:24
    * @Description: 退出登录
    **/
    @Override
    @PostMapping("/userlogout")
    public ResponseResult logout() {
        //1.取出身份令牌
        String jitToken = this.findJtiTokenFromCookie();
        //1.清除redis中的toen
        authService.delTokenFromRedis(jitToken);
        //2.清除cookie中的token
        this.delTokenFromCookie(jitToken);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    /**
    * @Author: gongfy
    * @Return:
    * @Date: 2020/9/2 20:41
    * @Description: 获取用户jwt令牌，返回页面展示用户信息  1.从cookie中获取短令牌，2.根据短令牌从redis中查询jwt令牌
    **/
    @Override
    @GetMapping("/userjwt")
    public JwtResult userjwt() {
        //1.从cookie中获取短令牌
        String jtiToken = this.findJtiTokenFromCookie();
        if (jtiToken == null){ // 从cookie中没有取到jittoken,说明用户没有登录,不显示用户信息即可
            return new JwtResult(CommonCode.FAIL,null);
        }
        // 2.根据短令牌从redis中查询jwt令牌
        AuthToken authToken = authService.findTokenFromRedis(jtiToken);
        if (authToken == null){ // 从缓存中没有取到说明用户没有登录
            return null;
        }
        return new JwtResult(CommonCode.SUCCESS,authToken.getJwt_token());
    }

    //从cookie中获取短令牌(身份令牌)
    public String findJtiTokenFromCookie(){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) (RequestContextHolder.getRequestAttributes());
        HttpServletRequest request = requestAttributes.getRequest();
        Map<String, String> map = CookieUtil.readCookie(request, "uid");
        if (!SysUtil.isNullOrEmpty(map) && !SysUtil.isNullOrEmpty(map.get("uid"))) {
            return map.get("uid");
        }
        return null;
    }

}
